%   Initialization
clear; close all; clc;

%   ========    Part 1: Plotting Data Sets   ========
fprintf('Plotting the data sets ...\n');
%   Load data --- read comma separated data
data = load('data1.txt');
%   Initialize the variables of data
X = data(:, 1);
y = data(:, 2);
%   Number of the training examples
m = length(y);
%   Plot Data
plotData(X, y);
%   Pause the program
fprintf('Program paused. Press any key to continue.\n'); pause;

%   ========    Part 2: Gradient Descent    ========
fprintf('Running the gradient descent ...\n');
%   Add a column of ones to X
X = [ones(m, 1), X];
%   Initialize the fitting parameters
theta = zeros(2, 1);
%   Gradient descent settings
iterations = 1500;
alpha = 0.01;
%   Compute and display the initial cost
fprintf('The initial cost: %f\n', computeCost(X, y, theta));
%   Run gradient descent
theta = gradientDescent(X, y, theta, alpha, iterations);
%   Print theta to screen
fprintf('Theta trained by gradient descent algorithm: %f %f\n', theta(1), theta(2));
%   Pause the program
fprintf('Program paused. Press any key to continue.\n'); pause;

%   ========    Part 3: Plotting Linear Fit    ========
fprintf('Plotting the linear fit ...\n');
%   Keep the previous plot visible
hold on;
%   Options: 'LineStyle' with '-' --- solid line
plot(X(:,2), X * theta, 'LineStyle','-');
%   Add the legend to the data and the linear fit 
legend('Training data', 'Linear regression');
%   Don't overlay any more plots on this figure
hold off;
%   Pause the program
fprintf('Program paused. Press any key to continue.\n'); pause;

%   ========    Part 4: Predicting Prices    ========
fprintf('Predicting prices ...\n');
%   Predict the result with the trained theta
predict1 = [1, 3.5] * theta;
fprintf('For population = 35,000, we predict a price of %f\n', predict1 * 10000);
%   Predict the result with the trained theta
predict2 = [1, 7] * theta;
fprintf('For population = 70,000, we predict a price of %f\n', predict2 * 10000);
%   Pause the program
fprintf('Program paused. Press any key to continue.\n'); pause;

%   ========    Part 5: Visualizing J(theta_0, theta_1)    ========
fprintf('Visualizing J(theta_0, theta_1) ...\n');
%   Generate the grid, over which we will calculate J
theta0_vals = linspace(-10, 10, 101);
theta1_vals = linspace(-1, 4, 101);
%   Initialize the J_vals to a matrix of zeros
J_vals = zeros(length(theta0_vals), length(theta1_vals));
%   Fill out the J_vals
for i = 1:length(theta0_vals)
    for j = 1:length(theta1_vals)
	  theta_vals = [theta0_vals(i); theta1_vals(j)];
	  J_vals(i,j) = computeCost(X, y, theta_vals);
    end
end
%   Because of the way meshgrids work in the surf command, we need to transpose J_vals before calling surf, or else the axes will be flipped
J_vals = J_vals';
%   Open a new figure window
figure;
%   Plot the surface ----- x - theta0_vals, y - theta1_vals, z - J_vals
surfc(theta0_vals, theta1_vals, J_vals);
% 	Set the x−axis label --- '\' can convert the text to mathmatical symbol
xlabel('\theta_0');
% 	Set the y−axis label --- '\' can convert the text to mathmatical symbol
ylabel('\theta_1');
%   Open a new figure window
figure;
%   Plot the contour --- plot J_vals as 15 contours spaced logarithmically between 0.01 and 100
contour(theta0_vals, theta1_vals, J_vals, logspace(-2, 2, 20));
% 	Set the x−axis label --- '\' can convert the text to mathmatical symbol
xlabel('\theta_0');
% 	Set the y−axis label --- '\' can convert the text to mathmatical symbol
ylabel('\theta_1');
%   Keep the previous plot visible
hold on;
%   Options: 'LineWidth' with 2 --- 
plot(theta(1), theta(2), 'rx', 'MarkerSize', 10, 'LineWidth', 2);
